//
//  UIView+Extension.swift
//  LiveTrivia
//
//  Created by Gesen on 2017/11/12.
//  Copyright © 2017年 LiveTrivia. All rights reserved.
//

import UIKit

extension UIView {
    
    static var nib: UINib {
        return UINib(nibName: String(describing: self), bundle: nil)
    }
    
    static func fromNib<T: UIView>() -> T {
        return Bundle.main.loadNibNamed(String(describing: self), owner: nil, options: nil)?.first as! T
    }
}

extension UIView {
    
    func debug() {
        backgroundColor = UIColor(
            red: CGFloat(arc4random_uniform(255)) / 255,
            green: CGFloat(arc4random_uniform(255)) / 255,
            blue: CGFloat(arc4random_uniform(255)) / 255,
            alpha: 1
        )
    }
    
    func shake(times: Int) {
        let anim = CAKeyframeAnimation(keyPath: "transform")
        anim.values = [
            NSValue(caTransform3D: CATransform3DMakeTranslation(-5, 0, 0 )),
            NSValue(caTransform3D: CATransform3DMakeTranslation( 5, 0, 0 ))
        ]
        anim.autoreverses = true
        anim.repeatCount = Float(times)
        anim.duration = 0.1
        
        layer.add(anim, forKey: nil)
    }
    
    func toImage(scale: CGFloat = UIScreen.main.scale) -> UIImage {
        return layer.toImage(scale: scale)
    }
    
    func getScale() -> CGFloat? {
        return layer.presentation()?.value(forKeyPath: "transform.scale") as? CGFloat
    }
    
    func setScale(x: CGFloat, y: CGFloat) {
        var transform = CATransform3DIdentity
        transform.m34 = 1.0 / -1000.0
        transform = CATransform3DScale(transform, x, y, 1)
        layer.transform = transform
    }
    
    func setTranslation(x: CGFloat, y: CGFloat) {
        transform = CGAffineTransform(translationX: x, y: y);
    }
    
    func setRotationX(_ x: CGFloat) {
        var transform = CATransform3DIdentity
        transform.m34 = 1.0 / -1000.0
        transform = CATransform3DRotate(transform, x.degreesToRadians(), 1.0, 0.0, 0.0)
        layer.transform = transform
    }
    
    func setRotationY(_ y: CGFloat) {
        var transform = CATransform3DIdentity
        transform.m34 = 1.0 / -1000.0
        transform = CATransform3DRotate(transform, y.degreesToRadians(), 0.0, 1.0, 0.0)
        layer.transform = transform
    }
    
    func setRotationZ(_ z: CGFloat) {
        var transform = CATransform3DIdentity
        transform.m34 = 1.0 / -1000.0
        transform = CATransform3DRotate(transform, z.degreesToRadians(), 0.0, 0.0, 1.0)
        layer.transform = transform
    }
    
    func setRotation(x: CGFloat, y: CGFloat, z: CGFloat) {
        var transform = CATransform3DIdentity
        transform.m34 = 1.0 / -1000.0
        transform = CATransform3DRotate(transform, x.degreesToRadians(), 1.0, 0.0, 0.0)
        transform = CATransform3DRotate(transform, y.degreesToRadians(), 0.0, 1.0, 0.0)
        transform = CATransform3DRotate(transform, z.degreesToRadians(), 0.0, 0.0, 1.0)
        layer.transform = transform
    }
    
    func setIdentity() {
        layer.transform = CATransform3DIdentity
    }
    
    func setRoundingCorners(_ corners: UIRectCorner) {
        let path = UIBezierPath(
            roundedRect: bounds,
            byRoundingCorners: corners,
            cornerRadii: CGSize(width: bounds.height * 0.5, height: bounds.height * 0.5)
        )
        let maskLayer = CAShapeLayer()
        maskLayer.frame = bounds
        maskLayer.path = path.cgPath
        layer.mask = maskLayer
    }
    
    func findFirstResponder() -> UIView? {
        guard !isFirstResponder else { return self }
        return subviews.compactMap { $0.findFirstResponder() }.first
    }
}

extension UIView {
    
    func subviewIndex(tap: UITapGestureRecognizer) -> Int? {
        let point = tap.location(in: self)
        return subviews.firstIndex { $0.frame.contains(point) }
    }
}

public extension UIView {
    
    func constraints(on anchor: NSLayoutYAxisAnchor) -> [NSLayoutConstraint] {
        guard let superview = superview else { return [] }
        return superview.constraints.filtered(view: self, anchor: anchor)
    }
    
    func constraints(on anchor: NSLayoutXAxisAnchor) -> [NSLayoutConstraint] {
        guard let superview = superview else { return [] }
        return superview.constraints.filtered(view: self, anchor: anchor)
    }
    
    func constraints(on anchor: NSLayoutDimension) -> [NSLayoutConstraint] {
        guard let superview = superview else { return [] }
        return constraints.filtered(view: self, anchor: anchor) + superview.constraints.filtered(view: self, anchor: anchor)
    }
    
}

extension NSLayoutConstraint {
    
    func matches(view: UIView, anchor: NSLayoutYAxisAnchor) -> Bool {
        if let firstView = firstItem as? UIView, firstView == view && firstAnchor == anchor {
            return true
        }
        if let secondView = secondItem as? UIView, secondView == view && secondAnchor == anchor {
            return true
        }
        return false
    }
    
    func matches(view: UIView, anchor: NSLayoutXAxisAnchor) -> Bool {
        if let firstView = firstItem as? UIView, firstView == view && firstAnchor == anchor {
            return true
        }
        if let secondView = secondItem as? UIView, secondView == view && secondAnchor == anchor {
            return true
        }
        return false
    }
    
    func matches(view: UIView, anchor: NSLayoutDimension) -> Bool {
        if let firstView = firstItem as? UIView, firstView == view && firstAnchor == anchor {
            return true
        }
        if let secondView = secondItem as? UIView, secondView == view && secondAnchor == anchor {
            return true
        }
        return false
    }
}

extension Array where Element == NSLayoutConstraint {
    
    func filtered(view: UIView, anchor: NSLayoutYAxisAnchor) -> [NSLayoutConstraint] {
        return filter { constraint in
            constraint.matches(view: view, anchor: anchor)
        }
    }
    func filtered(view: UIView, anchor: NSLayoutXAxisAnchor) -> [NSLayoutConstraint] {
        return filter { constraint in
            constraint.matches(view: view, anchor: anchor)
        }
    }
    func filtered(view: UIView, anchor: NSLayoutDimension) -> [NSLayoutConstraint] {
        return filter { constraint in
            constraint.matches(view: view, anchor: anchor)
        }
    }
    
}
